package edu.colorado.cs.correll.cudroplet.shaperecognition;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.JAXB;

import edu.colorado.cs.correll.cudroplet.shaperecognition.xml.Match;
import edu.colorado.cs.correll.cudroplet.shaperecognition.xml.ShapePosition;
import edu.colorado.cs.correll.cudroplet.shaperecognition.xml.ShapeRecognitionRuns;
import edu.colorado.cs.correll.cudroplet.shaperecognition.xml.TestRun;
import edu.colorado.cs.correll.cudroplet.shaperecognition.xml.TestType;

import processing.core.PApplet;

@SuppressWarnings("serial")
public class ResultsProcessing extends PApplet {

	private static final int MAX_DIFFERENCE = 10;
	private static final int MAX_DIFFERENCE2 = 50;
	private static final int MIN_LEN = 100;

	ShapeRecognitionRuns shapeRecognitionRuns;

	private Map<Double, Integer> positionMap = new HashMap<Double, Integer>();
	
	public void setup() {
		shapeRecognitionRuns = JAXB.unmarshal(createInput(getLoc()), ShapeRecognitionRuns.class);
		
		String[] header = new String[shapeRecognitionRuns.listShapePosition.shapePositionList.size()+1];
		header[0] = "Class";
		for(int i = 0; i < shapeRecognitionRuns.listShapePosition.shapePositionList.size(); i++) {
			ShapePosition shapePosition = shapeRecognitionRuns.listShapePosition.shapePositionList.get(i);
			header[i+1] = shapePosition.shapeName;
			positionMap.put(new Double(shapePosition.x), new Integer(i));
		}
		
		Map<Integer, TestType> testTypeMap = new HashMap<Integer, TestType>();
		for(TestType testType: shapeRecognitionRuns.listTestType.testTypeList) {
			testTypeMap.put(new Integer(testType.id), testType);
		}
		Map<Integer, int[]> truePositives = new HashMap<Integer, int[]>();
		
		for(TestRun testRun: shapeRecognitionRuns.listTestRun.testRunList) {
			for(Match match: testRun.matchList) {
				if(!truePositives.containsKey(new Integer(match.testId))) {
					truePositives.put(new Integer(match.testId), new int[shapeRecognitionRuns.listShapePosition.shapePositionList.size()]);
					for(int i = 0; i < shapeRecognitionRuns.listShapePosition.shapePositionList.size(); i++) {
						truePositives.get(new Integer(match.testId))[i] = 0;
					}
				}
				if(abs((float) (match.startX - match.endX)) < MAX_DIFFERENCE  && len2(match) > MIN_LEN * MIN_LEN) {
					int idx = getIndex(match.startX);
					if(idx >= 0) {
						truePositives.get(new Integer(match.testId))[idx]++;
					}
				}
			}
		}
		
		
		
		
		String[][] body = new String[testTypeMap.size()][shapeRecognitionRuns.listShapePosition.shapePositionList.size()+1];
		int i = 0;
		for(Map.Entry<Integer, TestType> e: testTypeMap.entrySet()) {
			TestType testType = e.getValue();
			body[i][0] = getTestTypeString(testType);
			for(int j = 0; j < shapeRecognitionRuns.listShapePosition.shapePositionList.size(); j++) {
				body[i][j+1] = 100.0 * truePositives.get(testType.id)[j]/shapeRecognitionRuns.listTestRun.testRunList.size() + "\\%";
			}
			i++;
		}
		printTable(header, body);
	}
	
	private String getTestTypeString(TestType testType) {
		return testType.similarityMeasure + " " + testType.shapeType + " threshold = " + testType.threshold;
	}

	private double len2(Match match) {
		double xlen = match.startX - match.endX;
		double ylen = match.startY - match.endY;
		return xlen * xlen + ylen * ylen;
	}

	private int getIndex(double startX) {
		int idx = -1;
		for(Double x: positionMap.keySet()) {
			if(abs((float) (startX + shapeRecognitionRuns.shapeDim - x.doubleValue())) < MAX_DIFFERENCE2) {
				idx = positionMap.get(x).intValue();
			}
		}
		return idx;
	}

	String getLoc() {
		String baseLoc = "/Users/charlesdietrich"; // "/home/common/"
		return baseLoc
				+ "/Dropbox/cu-droplet/simulator/processing/shape-recognition/results/results.xml";
	}
	
	static void printTable(String[] header, String[][] body) {
		println("\\begin{center}");
		println("\\begin{tabular}{|" + cs(1+header.length) + "}");
		println("\\hline");
		println(andConnect(header) + "\\\\ \\hline");
		for(String[] b: body) {
			println(andConnect(b) + "\\\\");
		}
		println("\\hline");
		println("\\end{tabular}");
		println("\\end{center}");
	}
	
	static String cs(int length) {
		String s = "";
		for(int i = 0; i < length; i++) {
			s += "c|";
		}
		return s;
	}
	
	static String andConnect(String[] strs) {
		String s = "";
		for(String str: strs) {
			s += "&" + str;
		}
		return s;
	}
}
